package com.ce.source.analysis.hashmap;

import java.util.concurrent.ConcurrentHashMap;

/**
 * @author ：xiaopingzhang8@creditease.cn
 * @Description ：ConcurrentHashMap源码分析
 * @ClassName ：ConcurrentHashMapAnalyse
 * @Company ：普信恒业科技发展（北京）有限公司
 * @date ：2017/11/22 16:15
 */
public class ConcurrentHashMapAnalyse {
    public static void main(String[] args) {
        analysePut();
    }


    /**
     * <p>
     *     jdk1.7 ConcurrentHashMap
     *     <ol>
     *         <li>
     *             ConcurrentHashMap线程安全是基于segment加锁实现的，segment相当于一个一个小的hashMap。因为针对这个hashMap加锁，相当于hashTable性能会低，
     *             所以将hashMap分成一个一个的小单元，针对小单元加锁。
     *         </li>
     *         <li>
     *             segment：segment数量的大小=初始容量的最小2次幂
     *                      while (ssize < concurrencyLevel) {
     ssize <<= 1;
     }
     *             segment 初始默认值16
     *         </li>
     *         <li>
     *             put:
     *              <ol>
     *                  <li>
     *                      首先根据key计算hash
     *                  </li>
     *                  <li>
     *                      根据hash>>>偏移量 & segmentMask计算segment索引，将数据落在第几个segment
     *                  </li>
     *                  <li>
     *                       如果取到的segment[i]为空，初始化segment
     *                  </li>
     *                  <li>
     *                     segment.put
     *                      如果hash值相同，则转成链表存储
     *                      否则，根据数组存储
     *                  </li>
     *                  <li>
     *                      如果数据的长度>threshold则进行扩容，扩容只是针对segment扩容，不会影响到所有的整个hashMap的变化
     *                  </li>
     *             </ol>
     *         </li>
     *     </ol>
     * </p>
     *
     *
     * <p>
     *   jdk1.8 ConcurrentHashMap
     *
     *   <ol>
     *       <li>
     *          根据初始容量，初始化table size  table.size=1.5倍的2的最小次幂<br/>
     *          tableSizeFor(initialCapacity + (initialCapacity >>> 1) + 1))
     *       </li>
     *       <li>
     *          计算key的hash值 <u>int hash = spread(key.hashCode())</u>
     *       </li>
     *       <li>
     *           判断table，如果为空初始化table<br />
     *            initTable()
     *           <br />否则插入数据
     *       </li>
     *       <li>
     *           if tabAt(tab, i = (n - 1) & hash)) == null<br />
     *              插入数据（由于采用的是cas原子操作，是线程安全的）<br />
     *           else
     *              插入数据（链表 or 树）
     *       </li>
     *       <li>
     *           如果链表的长度大于等于8，则转成红黑二叉树<br />
     *            if (binCount >= TREEIFY_THRESHOLD)<br />
                        treeifyBin(tab, i);
     *       </li>
     *   </ol>
     * </p>
     */
    public static void analysePut(){
        ConcurrentHashMap<Object,Object> map= new ConcurrentHashMap<Object,Object>(10);
        map.put("a","data-a");
        map.put("b","data-a");
        map.put("c","data-a");
        map.put(97,"data-97");
        map.put(98,"data-98");

    }
}
